/**
 * 2010-5-18
 * InnovationServer
 * @author lyh
 */
package labox.innovation.gameserver.model.quest;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import labox.innovation.gameserver.GameTimeController;
import labox.innovation.gameserver.model.L2Object;
import labox.innovation.gameserver.model.Scene;
import labox.innovation.gameserver.model.actor.L2Npc;
import labox.innovation.gameserver.model.actor.instance.FuzeNpcInstance;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.listener.INpcFaceStateListenr;
import labox.innovation.gameserver.model.quest.dataset.QuestDataSet;
import labox.innovation.gameserver.network.serverpackets.StatusUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuestStateLogic {
	private static final Logger _log = LoggerFactory.getLogger(QuestStateLogic.class.getName());
    
	private StringBuilder _logMsg = new StringBuilder();

	private QuestStateLogic() {
	}

	private static class SingletonHolder {
		protected static final QuestStateLogic _instance = new QuestStateLogic();
	}

	public static QuestStateLogic getInstance() {
		return SingletonHolder._instance;
	}
	
	// ------------ QuestHandle -----------------------------

	/**
	 * 接受任务逻辑
	 */
	public boolean acceptQuestHandle(QuestState qs, L2Npc npc) {
		if (qs != null) {
			FuzePcInstance player = qs.getPlayer();

			QuestDataSet qds = qs.getQuest().getQuestDataSet();

			// --周期任务逻辑
			String questCycle = qds.getQuestCycle();
			if (questCycle != null && !questCycle.equals("-1")) {// 周期性任务逻辑
				String cycle = (String) qs.get("<cycle>");// 周期
				if (cycle != null) {
					Date nowDate = GameTimeController.getInstance().getNowDate();
					String accept_date = (String) qs.get("<accept_date>");
					Long oldTime = Long.parseLong(accept_date == null ? "0" : accept_date);// 上一次接受时间
					Date oldDate = new Date(oldTime);
					int nowDate_num = getCycleCounte(nowDate, cycle);
					int oldDate_num = getCycleCounte(oldDate, cycle);
					int count = qs.getInt("<acceptCount>");// 累计接受次数
					if (nowDate_num == oldDate_num) {// 在同一周期内判断是否超过限制接受次数
						int acceptCount = qds.getAcceptCount();
						if (acceptCount > count) {
							qs.set("<acceptCount>", Integer.toString(++count));// 更新接受次数
						} else {
							player.questMSG = "该任务同一周期只能接受[" + acceptCount + "]次";
							return false;
						}
					} else {// 周期变化重新计算次数
						qs.set("<acceptCount>", "1");// 接受次数
					}
					qs.set("<accept_date>", Long.toString(nowDate.getTime()));// 接受时间

				} else {
					Date nowDate = GameTimeController.getInstance().getNowDate();
					int nowDate_num = getCycleCounte(nowDate, questCycle);
					qs.set("<cycle>", questCycle);// 周期
					qs.set("<accept_date>", Long.toString(nowDate.getTime()));// 接受时间
					qs.set("<acceptCount>", "1");// 接受次数
				}
			}
			_logMsg.setLength(0);
			_logMsg.append("接受任务:任务模板Id:").append(qs.getQuestName()).append("||任务名:").append(qs.getQuest().getDescr());
			_log.info(_logMsg.toString(), player.getObjectId(), player.getName());

			// ----更新npc表情----

			return true;
		}
		return false;
	}

	/**
	 * 接受刷新操作
	 * 
	 * @param qs
	 *            2010-5-20
	 * @author lyh
	 */
	public void acceptRefreshHandle(QuestState qs) {
		if (qs != null) {
			FuzePcInstance player = qs.getPlayer();
			player.removeMayQuestList(qs.getQuestName());// 刷新可接任务列表
			player.refreshQuestList();// 刷新已接任务列表
			updateNpcFace(player);
		}
	}

	/**
	 * 完成任务逻辑
	 * 
	 * @param st
	 *            2010-5-20
	 * @author lyh
	 */
	public void completeQuestHandle(QuestState st) {
		if (st != null) {
			QuestDataSet qds = st.getQuest().getQuestDataSet();
			FuzePcInstance player = st.getPlayer();
			updateNpcFace(player);
			_logMsg.setLength(0);
			_logMsg.append("完成任务:任务模板Id:").append(st.getQuestName()).append("||任务名:").append(st.getQuest().getDescr());
			_log.info(_logMsg.toString(), player.getObjectId(), player.getName());
		}
	}

	/**
	 * 退出任务处理逻辑
	 * 
	 * @param qs
	 * @param repeatable
	 * @return 2010-5-19
	 * @author lyh
	 */
	public QuestState exitQuestHandle(QuestState qs, boolean repeatable) {
		QuestDataSet qds = qs.getQuest().getQuestDataSet();
		// --周期任务逻辑
		String questCycle = qds.getQuestCycle();
		_logMsg.setLength(0);
		_logMsg.append("退出任务:任务模板Id:").append(qs.getQuestName()).append("||任务名:").append(qs.getQuest().getDescr());
		_log.info(_logMsg.toString(), qs.getPlayer().getObjectId(), qs.getPlayer().getName());
		if (questCycle != null && !questCycle.equals("-1")) {// 周期性任务逻辑
			return exitCycleQuest(qs);
		} else {
			return exitQuest(qs, repeatable);
		}
	}

	private QuestState exitQuest(QuestState qs, boolean repeatable) {

		// 删除此角色notifyDeath列表这一任务，如果它在这个列表中
		qs.getPlayer().removeNotifyQuestOfDeath(qs);

		if (qs.isCompleted())
			return qs;

		// 说任务完成
		qs.setState(State.COMPLETED);

		// 清理注册任务物品
		int[] itemIdList = qs.getQuest().getRegisteredItemIds();
		if (itemIdList != null) {
			for (int i = 0; i < itemIdList.length; i++) {
				_logMsg.setLength(0);
				_logMsg.append("退出任务清理任务物品:任务模板Id:").append(qs.getQuestName()).append("||任务名:").append(qs.getQuest().getDescr());
				qs.takeItems(itemIdList[i], -1, _logMsg.toString());
			}
		}
		Map<String, String> _vars = qs.getVars();
		// If quest is repeatable, delete quest from list of quest of the player
		// and from database (quest CAN be created again => repeatable)
		// 如果任务是重复的，删除的玩家列表的任务和任务从数据库（任务可以再次接=>可重复）
		if (repeatable) {
			qs.getPlayer().delQuestState(qs.getQuestName());
			Quest.deleteQuestInDb(qs);

			qs.setVars(null);
		} else {
			// Otherwise, delete variables for quest and update database (quest
			// CANNOT be created again => not repeatable)
			// 否则，删除和更新的任务数据库变量（任务不能重复接=>不可重复）
			if (_vars != null) {
				for (String var : _vars.keySet())
					qs.unset(var);
			}

			Quest.updateQuestInDb(qs);
		}
		qs.getPlayer().removeQuestList(qs.getQuestName());// 清除已接任务(如:放弃(完成)任务时刷新)
		qs.getPlayer().refreshMayQuestList();// 刷新可接任务列表
		qs.getPlayer().refreshQuestList();// 刷新已经任务列表

		updateNpcFace(qs.getPlayer());
		return qs;

	}

	/**
	 * 完成或退出周期任务逻辑
	 * 
	 * @param qs
	 * @param repeatable
	 * @return 2010-5-19
	 * @author lyh
	 */
	private QuestState exitCycleQuest(QuestState qs) {

		// 清理注册任务物品
		int[] itemIdList = qs.getQuest().getRegisteredItemIds();
		if (itemIdList != null) {
			for (int i = 0; i < itemIdList.length; i++) {
				_logMsg.setLength(0);
				_logMsg.append("退出任务清理任务物品:任务模板Id:").append(qs.getQuestName()).append("||任务名:").append(qs.getQuest().getDescr());
				qs.takeItems(itemIdList[i], -1, _logMsg.toString());
			}
		}
		Map<String, String> _vars = qs.getVars();
		String cycle = (String) qs.get("<cycle>");// 周期
		String accept_date = (String) qs.get("<accept_date>");
		Long oldTime = Long.parseLong(accept_date == null ? "0" : accept_date);// 上一次接受时间
		int count = qs.getInt("<acceptCount>");// 累计接受次数

		if (_vars != null) {
			for (String var : _vars.keySet())
				qs.unset(var);
		}

		qs.set("<cycle>", cycle);// 周期
		qs.set("<accept_date>", Long.toString(oldTime));// 接受时间
		qs.set("<acceptCount>", Integer.toString(count));// 接受次数
		qs.setState(State.CREATED);
		Quest.updateQuestInDb(qs);

		qs.getPlayer().removeQuestList(qs.getQuestName());// 清除已接任务(如:放弃(完成)任务时刷新)
		qs.getPlayer().refreshMayQuestList();// 刷新可接任务列表
		qs.getPlayer().refreshQuestList();// 刷新已经任务列表

		updateNpcFace(qs.getPlayer());
		return qs;
	}

	private int getCycleCounte(Date date, String dateField) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);
		int field = 0;
		if (dateField == null || dateField.equals(""))
			return -1;
		if (dateField.equals("y")) {
			field = Calendar.YEAR;
		} else if (dateField.equals("m")) {
			field = Calendar.MONTH;
		} else if (dateField.equals("w")) {
			field = Calendar.WEEK_OF_YEAR;
		} else if (dateField.equals("d")) {
			field = Calendar.DAY_OF_YEAR;
		}
		if (field > 0)
			return cal.get(field);
		return -1;
	}

	private void test(QuestState qs) {
		String cycle = (String) qs.get("<cycle>");// 周期
		String accept_date = (String) qs.get("<accept_date>");
		Long oldTime = Long.parseLong(accept_date == null ? "0" : accept_date);// 上一次接受时间
		int count = qs.getInt("<acceptCount>");// 累计接受次数
		System.out.println("<cycle>" + cycle);
		System.out.println("<accept_date>" + oldTime);
		System.out.println("<acceptCount>" + count);
	}

	/**
	 * 更新npc表情
	 * 
	 * @param player
	 * @param npc
	 *            2010-5-20
	 * @author lyh
	 */
	/**
	 * @param player
	 *            2010-5-20
	 * @author lyh
	 */
	public void updateNpcFace(FuzePcInstance player) {
//		Collection<L2Character> objs = player.getKnownList().getKnownCharacters().values();
//		
//		for (L2Character obj : objs) {
//			if (obj instanceof FuzeNpcInstance) {
//				updateNpcFaceSendPacket(player, (L2Npc) obj);
//			}
//		}
		
		Scene scene = player.getScene();
		Map<Long, L2Object> playables = scene.getVisibleObjects();
		Iterator<Entry<Long, L2Object>> it = playables.entrySet().iterator();
		
		while (it.hasNext()) {
			L2Object playable = it.next().getValue();
			
			if (playable instanceof FuzeNpcInstance) { //-- 当前场景中NPC
				updateNpcFaceSendPacket(player, (L2Npc) playable);
			}
		}
	}

	private void updateNpcFaceSendPacket(FuzePcInstance player, L2Npc npc) {
		if (npc == null)
			return;
		QuestCompletedStatus _isQuestCompleted = new QuestCompletedStatus();
		_isQuestCompleted.setHasCompleted(false);
		int type = player.getNpcQuestFace(npc, _isQuestCompleted);
		
		StatusUpdate su = new StatusUpdate(npc.getObjectId());
		su.addAttribute(StatusUpdate.P_ATK_FACE, type);
		player.sendPacket(su);
		
		for (INpcFaceStateListenr listener: player.getNpcFaceStateListeners()) {  //-- 通知NPC表情状态监听器
			listener.notifyNpcStateChanged(npc);
		}
		
//		if (type != L2Radar.GEN_NPC) {
//			System.out.println(npc.getName());
//			System.out.println(type);
//			npc.sendInfoEx(player);
//		}
		    
		
//		if (type != L2Radar.GEN_NPC || _isQuestCompleted.isHasCompleted()) {  //-- NPC图标有状态或者任务已经完成
//			StatusUpdate su = new StatusUpdate(npc.getObjectId());
//			su.addAttribute(StatusUpdate.P_ATK_FACE, type);
//			System.out.println("npc::::::::::::" + npc.getName());
//			System.out.println("KKKKKKKKKKKKKKKKKKKKKKKK: " + type);
//			player.sendPacket(su);
//		}
	}
	
	/**
	 * java中对于boolean、String、int等类型传参时候使用的是拷贝，因此当传boolean等类型值出来的时候有必要使用自定义类
	 * @author Frank
	 *
	 */
	public class QuestCompletedStatus {
		private boolean hasCompleted;

		public boolean isHasCompleted() {
			return hasCompleted;
		}

		public void setHasCompleted(boolean hasCompleted) {
			this.hasCompleted = hasCompleted;
		}
		
	}
	
	
}
